use std::cmp::Ordering;
use std::fmt::Display;

#[derive(Debug)]
struct User {
    name: String,
    sex: bool,
}

struct Pair<T> {
    x: T,
    y: T,
}

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

impl<T> Pair<T>
where
    T: Display + PartialOrd,
{
    fn cmp_display(&self) {
        if self.x > self.y {
            println!("The largest member is x = {}", self.x);
        } else {
            println!("The largest member is y = {}", self.y);
        }
    }
}

impl Display for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(
            f,
            "Debug: Complex {{ name: {}, sex: {} }}",
            self.name, self.sex
        )
    }
}

impl PartialOrd for User {
    fn partial_cmp(&self, other: &User) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for User {
    fn cmp(&self, other: &User) -> Ordering {
        self.name.len().cmp(&other.name.len())
    }
}

impl PartialEq for User {
    fn eq(&self, other: &User) -> bool {
        self.name.len() == other.name.len()
    }
}

impl Eq for User {}

fn main() {
    let p1 = Pair::new(1, 2);
    let p2 = Pair::new("1", "2");
    let p3 = Pair::new(
        User {
            name: String::from("baw"),
            sex: false,
        },
        User {
            name: String::from("bbq"),
            sex: true,
        },
    );
    p2.cmp_display();
    p1.cmp_display();
    p3.cmp_display();
    println!("Hello, world!");
}
